package dao;

import static org.hibernate.criterion.Example.create;

import java.io.File;
import java.math.BigDecimal;
import java.util.List;

import org.hibernate.LockMode;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;


public class DAOGenerico<T> implements DAO<T>{
	
//	"src/recursos/hibernate.cfg.xml";
//	E:\\Trabajos\\Programas\\PruebaDao\\src\\recursos\\hibernate.cfg.xml

	private static final String RUTA_ARCH_CONF_HIBERNATE = "E:\\Trabajos\\Programas\\ProyectoCadenaHotelera\\src\\hibernate.cfg.xml";

	private final SessionFactory sessionFactory = getSessionFactory();
	
	private Class<T> clase;
	
	public DAOGenerico(Class<T> clase) 
	{
		this.clase = clase;
	}
	
	protected SessionFactory getSessionFactory() 
	{
		try 
		{
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure(new File(RUTA_ARCH_CONF_HIBERNATE)).buildSessionFactory();
        } 
		catch (Throwable ex) 
        {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
	}

	public void persist(T transientInstance) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			sessionFactory.getCurrentSession().persist(transientInstance);
			currentSession.getTransaction().commit();
		} 
		catch (RuntimeException re) 
		{
			throw re;
		}
	}

	public void attachDirty(T instance) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			sessionFactory.getCurrentSession().saveOrUpdate(instance);
			currentSession.getTransaction().commit();
		} 
		catch (RuntimeException re) 
		{
			throw re;
		}
	}

	public void attachClean(T instance) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			sessionFactory.getCurrentSession().lock(instance, LockMode.NONE);
			currentSession.getTransaction().commit();
		} catch (RuntimeException re) 
		{
			throw re;
		}
	}

	public void delete(T persistentInstance) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			sessionFactory.getCurrentSession().delete(persistentInstance);
			currentSession.getTransaction().commit();
		} 
		catch (RuntimeException re) 
		{
			throw re;
		}
	}

	public T merge(T detachedInstance) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			T result = (T) sessionFactory.getCurrentSession().merge(detachedInstance);
			currentSession.getTransaction().commit();
			return result;
		} 
		catch (RuntimeException re) 
		{
			throw re;
		}
	}

	public T findById(BigDecimal id) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			T instance = (T) sessionFactory.getCurrentSession().get(clase , id);
			currentSession.getTransaction().commit();
			return instance;
		} 
		catch (RuntimeException re) 
		{
			throw re;
		}
	}

	public T findById(Integer id) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			T instance = (T) sessionFactory.getCurrentSession().get(clase , id);
			currentSession.getTransaction().commit();
			return instance;
		} 
		catch (RuntimeException re) 
		{
			throw re;
		}
	}
	
	public List<T> findByExample(T instance) 
	{
		try 
		{
			Session currentSession = sessionFactory.getCurrentSession();
			currentSession.beginTransaction();
			List<T> results = (List<T>) sessionFactory.getCurrentSession().createCriteria(clase).add(create(instance)).list();
			currentSession.getTransaction().commit();
			return results;
		} 
		catch (RuntimeException re) 
		{
			throw re;
		}
	}
}
